<?php

declare(strict_types=1);

namespace App\Admin\Listener;

use App\Admin\Model\System\SystemUser;
use App\Admin\Service\System\SystemLoginLogService;
use DI\DependencyException;
use DI\NotFoundException;
use Newbie\Cache\Redis;
use Newbie\Event\UserLoginAfter;
use Newbie\helper\Str;

/**
 * Class LoginListener
 */
class LoginListener {
    /**
     * @param UserLoginAfter $event
     * @throws DependencyException
     * @throws NotFoundException
     */
    public function process (UserLoginAfter $event) {
        $service = container()->get(SystemLoginLogService::class);
        $redis   = container()->get(Redis::class);
        $agent   = request()->header('user-agent');
        $ip      = request()->ip();
        $service->save([
            'username'    => $event->userinfo['username'],
            'ip'          => $ip,
            'ip_location' => Str::ipToRegion($ip),
            'os'          => $this->os($agent),
            'browser'     => $this->browser($agent),
            'status'      => !$event->loginStatus,
            'message'     => $event->message,
            'login_time'  => date('Y-m-d H:i:s')
        ]);
        $key = sprintf("Token:%s", $event->userinfo['id']);
        $redis->exists($key) && $redis->del($key);
        ($event->loginStatus && $event->token) && $redis->set($key, $event->token, config('jwt.ttl'));

        if ($event->loginStatus) {
            $event->userinfo['login_ip']   = $ip;
            $event->userinfo['login_time'] = date('Y-m-d H:i:s');
            SystemUser::query()->where('id', $event->userinfo['id'])->update([
                'login_ip'   => $ip,
                'login_time' => date('Y-m-d H:i:s'),
            ]);
        }
    }

    /**
     * @param $agent
     * @return string
     */
    private function os ($agent): string {
        if (false !== stripos($agent, 'win') && preg_match('/nt 6.1/i', $agent)) {
            return 'Windows 7';
        }
        if (false !== stripos($agent, 'win') && preg_match('/nt 6.2/i', $agent)) {
            return 'Windows 8';
        }
        if (false !== stripos($agent, 'win') && preg_match('/nt 10.0/i', $agent)) {
            return 'Windows 10';
        }
        if (false !== stripos($agent, 'win') && preg_match('/nt 11.0/i', $agent)) {
            return 'Windows 11';
        }
        if (false !== stripos($agent, 'win') && preg_match('/nt 5.1/i', $agent)) {
            return 'Windows XP';
        }
        if (false !== stripos($agent, 'linux')) {
            return 'Linux';
        }
        if (false !== stripos($agent, 'mac')) {
            return 'Mac';
        }
        return t('jwt.unknown');
    }

    /**
     * @param $agent
     * @return string
     */
    private function browser ($agent): string {
        if (false !== stripos($agent, "MSIE")) {
            return 'MSIE';
        }
        if (false !== stripos($agent, "Edg")) {
            return 'Edge';
        }
        if (false !== stripos($agent, "Chrome")) {
            return 'Chrome';
        }
        if (false !== stripos($agent, "Firefox")) {
            return 'Firefox';
        }
        if (false !== stripos($agent, "Safari")) {
            return 'Safari';
        }
        if (false !== stripos($agent, "Opera")) {
            return 'Opera';
        }
        return t('jwt.unknown');
    }
}